package it.fuesi.synotools.services.tasks.filestation;

import android.app.DownloadManager;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import it.fuesi.synotools.R;
import it.fuesi.synotools.activities.FileStationFileDetailActivity;
import it.fuesi.synotools.helpers.FormatHelper;
import it.fuesi.synotools.helpers.LayoutHelper;
import it.fuesi.synotools.model.base.VoidDataObject;
import it.fuesi.synotools.model.base.VoidResponse;
import it.fuesi.synotools.model.filestation.FileStationClientParameters;
import it.fuesi.synotools.services.cache.CacheService;
import it.fuesi.synotools.services.client.FileStationClient;
import it.fuesi.synotools.services.client.ServiceClientFactory;
import it.fuesi.synotools.services.tasks.base.BaseTask;
import retrofit.client.Header;
import retrofit.client.Response;

/**
 * Created by pascotto on 17/10/14.
 */
public class DownloadFile extends BaseTask<VoidResponse, VoidDataObject, FileStationClientParameters> {

    private static final String TAG = DownloadFile.class.getName();
    private static final String DOWNLOAD_URI_SUFFIX = "/webapi/FileStation/file_download.cgi?api=SYNO.FileStation.Download&version=1&method=download&mode=download";

    public DownloadFile(Context context){
        super(context);
    }

    public final String getUrl(String filePath){
        return ServiceClientFactory.getEndpoint(ServiceClientFactory.getSynoConfig()) + DOWNLOAD_URI_SUFFIX + "&sid=" + CacheService.getSid(getContext()) + "&path=" + FormatHelper.urlEncode(filePath);
    }

    @Override
    protected boolean isCancelable() {
        return true;
    }

    @Override
    protected String getCacheKey() {
        return null;
    }

    private void updateProgress(long currentSize, long totalSize){
        publishProgress(getContext().getString(R.string.progress_downloading) + FormatHelper.formatPercent(((double)currentSize / (double)totalSize) * (double)100));
    }


    private void downloadWithManager(String filePath, String fileName){
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(getUrl(filePath)));
        request.setDescription("Downloading " + fileName);
        request.setTitle("FileStation Download");
        request.setVisibleInDownloadsUi(true);

// in order for this if to run, you must use the android 3.2 to compile your app
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            request.allowScanningByMediaScanner();
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        }else{
            request.setShowRunningNotification(true);
        }
        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);

// get download service and enqueue file
        DownloadManager manager = (DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE);
        manager.enqueue(request);

    }


    private void downloadWithRetrofit(String filePath, String fileName) throws Exception{
        publishProgress(getContext().getString(R.string.progress_download_started));


        FileStationClient client = ServiceClientFactory.getClient(FileStationClient.class);

        Response res = client.downloadFile(FormatHelper.urlEncode(filePath));

        int lenghtOfFile = 0;

        for(Header h : res.getHeaders()){
            if(h != null && h.getName() != null && h.getName().equals("Content-Length"))
                lenghtOfFile = Integer.parseInt(h.getValue());
        }

        Log.d(TAG, "downloadWithRetrofit.lenghtOfFile --> " + lenghtOfFile);

        InputStream input = res.getBody().in();

        File downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
        //create a new file, specifying the path, and the filename
        //which we want to save the file as.
        File destination = new File(downloadsDir,fileName);

        if(destination.exists())
            destination.delete();

        OutputStream output = new FileOutputStream(destination);
        byte data[] = new byte[1024];
        long total = 0;
        boolean aborted=false;
        int count = 0;
        int updateBuffer = 0;
        while ((count = input.read(data)) != -1) {
            if ( isCancelled()) {
                Log.i(TAG,"Abort signal received. Aborting download..");
                output.flush();
                // closing streams
                output.close();
                input.close();
                aborted=true;
                break;
            }
            total += count;
            // publishing the progress....
            // After this onProgressUpdate will be called
            if(updateBuffer == 10){
                updateProgress((int) total, lenghtOfFile);
                updateBuffer = 0;
            }else
                updateBuffer++;


            // writing data to file
            output.write(data, 0, count);
        }
        // flushing output
        output.flush();
        // closing streams
        output.close();
        input.close();

    }

    @Override
    public VoidResponse run(FileStationClientParameters params)  throws Exception{
        final String fileName = params.getName();
        final String filePath = params.getFile_path();

        //downloadWithManager(filePath,fileName);

        downloadWithRetrofit(filePath, fileName);

        return new VoidResponse(true);

    }

    @Override
    protected void onPostExecute(VoidResponse voidResponse) {
        super.onPostExecute(voidResponse);

        if (voidResponse != null && voidResponse.isSuccess()){
            LayoutHelper.showToast(getContext(), getContext().getString(R.string.toast_download_complete));
        }

        ((FileStationFileDetailActivity)getContext()).onDownloadFinished();
    }

    @Override
    protected void onCancelled() {
        super.onCancelled();

        Log.d(TAG, "OnCanceled --> ");

        hideProgress();

        LayoutHelper.showToast(getContext(), getContext().getString(R.string.toast_download_aborted));
    }
}
